
#include "usb_device.h"
#include "usbd_customhid.h"
#include "usbd_ctlreq.h"
#include "stdint.h"
#include "usb_midi.h"
#include "usbd_conf.h"

extern USBD_HandleTypeDef hUsbDeviceFS;


__ALIGN_BEGIN uint8_t USBD_CUSTOM_HID_CfgFSDesc[USB_CUSTOM_HID_CONFIG_DESC_SIZ] __ALIGN_END = 
{
  0x09, /* bLength: Configuration Descriptor size */
  USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
  USB_CUSTOM_HID_CONFIG_DESC_SIZ,
  0x00,
  0x02, /*bNumInterfaces: 2 interface*/
  0x01, /*bConfigurationValue: Configuration value*/
  0x00, /*iConfiguration: Index of string descriptor describing the configuration*/
  0xC0, /*bmAttributes: bus powered */
  0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/

  /* Standard AC Interface Descriptor */
  0x09, /*bLength: Interface Descriptor size*/
  USB_DESC_TYPE_INTERFACE, /*bDescriptorType: Interface descriptor type*/
  0x00, /*bInterfaceNumber: Number of Interface*/
  0x00, /*bAlternateSetting: Alternate setting*/
  0x00, /*bNumEndpoints*/
  0x01, /*bInterfaceClass: Audio*/
  0x01, /*bInterfaceSubClass : Audio Control*/
  0, /*nInterfaceProtocol*/
  0, /*iInterface: Index of string descriptor*/

  /* Class-specific AC Interface Descriptor */
  0x09, /*bLength: Interface Descriptor size*/
  0x24, /*bDescriptorType: Class-specific interface descriptor type*/
  0x01, /*bDescriptorSubType: Header*/
  0x00, /*bcdADC: Revision of class specification - 1.0*/
  0x01,
  0x09, /*wTotalLength: Total size of class specific descriptor*/
  0x00,
  0x01, /*bInCollection: Number of streaming interfaces*/
  0x01, /*baInterfaceNr : MIDIStreaming interface 1 belongs to this AudioControl interface*/

  /* Standard MS Interface Descriptor */
  0x09, /*bLength: Interface Descriptor size*/
  USB_DESC_TYPE_INTERFACE, /*bDescriptorType: Interface descriptor type*/
  0x01, /*bInterfaceNumber: Number of Interface*/
  0x00, /*bAlternateSetting: Alternate setting*/
  0x02, /*bNumEndpoints*/
  0x01, /*bInterfaceClass: Audio*/
  0x03, /*bInterfaceSubClass : MIDI Streaming*/
  0, /*nInterfaceProtocol*/
  0, /*iInterface: Index of string descriptor*/

  /* Class-specific MS Interface Descriptor */
  0x07, /*bLength: Interface Descriptor size*/
  0x24, /*bDescriptorType: Class-specific interface descriptor type*/
  0x01, /*bDescriptorSubType: MS Header*/
  0x00, /*bcdADC: Revision of class specification*/
  0x01,
  0x41, /*wTotalLength: Total size of class specific descriptor*/
  0x00,

  /* MIDI IN Jack Descriptor (Embedded) */
  0x06, /*bLength: Size of this descriptor*/
  0x24, /*bDescriptorType: Class-specific interface descriptor type*/
  0x02, /*bDescriptorSubType: MIDI IN Jack*/
  0x01, /*bJackType: Embedded*/
  0x01, /*bJackID: ID of this Jack*/
  0x00, /*iJack*/

  /* MIDI IN Jack Descriptor (External) */
  0x06, /*bLength: Size of this descriptor*/
  0x24, /*bDescriptorType: Class-specific interface descriptor type*/
  0x02, /*bDescriptorSubType: MIDI IN Jack*/
  0x02, /*bJackType: External*/
  0x02, /*bJackID: ID of this Jack*/
  0x00, /*iJack*/

  /* MIDI OUT Jack Descriptor (Embedded) */
  0x09, /*bLength: Size of this descriptor*/
  0x24, /*bDescriptorType: Class-specific interface descriptor type*/
  0x03, /*bDescriptorSubType: MIDI OUT Jack*/
  0x01, /*bJackType: Embedded*/
  0x03, /*bJackID: ID of this Jack*/
  0x01, /*bNrInputPins: Number of Input Pins of this Jack*/
  0x02, /*BaSourceID: ID of the Entry to which this Pin is connected*/
  0x01, /*BaSourceID: Output Pin number of the Entry to which this Input Pin is connected*/
  0x00, /*iJack*/

  /* MIDI OUT Jack Descriptor (External) */
  0x09, /*bLength: Size of this descriptor*/
  0x24 , /*bDescriptorType: Class-specific interface descriptor type*/
  0x03, /*bDescriptorSubType: MIDI OUT Jack*/
  0x02, /*bJackType: External*/
  0x04, /*bJackID: ID of this Jack*/
  0x01, /*bNrInputPins: Number of Input Pins of this Jack*/
  0x01, /*BaSourceID: ID of the Entry to which this Pin is connected*/
  0x01, /*BaSourceID: Output Pin number of the Entry to which this Input Pin is connected*/
  0x00, /*iJack*/

  /* Standard Bulk OUT Endpoint Descriptor */
  0x09, /*bLength: Size of this descriptor*/
  USB_DESC_TYPE_ENDPOINT, /*bDescriptorType: Endpoint descriptor type*/
  0x01, /*bEndpointAddress: OUT Endpoint 1*/
  0x02, /*bmAttributes: Bulk, not shared.*/
  0x40, /*wMaxPacketSize 64*/
  0x00,
  0x00, /*bInterval*/
  0x00, /*bRefresh*/
  0x00, /*bSynchAddress*/

  /* Class-specific MS Bulk OUT Endpoint Descriptor */
  0x05, /*bLength: Size of this descriptor*/
  0x25, /*bDescriptorType: Class-specific endpoint descriptor type*/
  0x01, /*bDescriptorSubType: MS General*/
  0x01, /*bNumEmbMIDIJack: Number of embedded MIDI IN Jack*/
  0x01, /*BaAssocJackID: ID of the Embedded MIDI IN Jack*/

  /* Standard Bulk IN Endpoint Descriptor */
  0x09, /*bLength: Size of this descriptor*/
  USB_DESC_TYPE_ENDPOINT, /*bDescriptorType: Endpoint descriptor type*/
  0x81, /*bEndpointAddress: IN Endpoint 1*/
  0x02, /*bmAttributes: Bulk, not shared.*/
  0x40, /*wMaxPacketSize 64*/
  0x00,
  0x00, /*bInterval*/
  0x00, /*bRefresh*/
  0x00, /*bSynchAddress*/
  
  /* Class-specific MS Bulk OUT Endpoint Descriptor */
  0x05, /*bLength: Size of this descriptor*/
  0x25, /*bDescriptorType: Class-specific endpoint descriptor type*/
  0x01, /*bDescriptorSubType: MS General*/
  0x01, /*bNumEmbMIDIJack: Number of embedded MIDI OUT Jack*/
  0x03 /*BaAssocJackID: ID of the Embedded MIDI OUT Jack*/
};


uint8_t USB_HID_Send(uint8_t *data, uint16_t len)
{
    uint8_t usb_midi_data[128]; // USB MIDI 数据缓冲区，大小根据需求调整
    uint8_t usb_data_length = 0; // 有效数据长度
    uint8_t cin = 0; // USB MIDI CIN 字段（Code Index Number）
    uint8_t i;

    // 初始化 USB MIDI 数据缓冲区
    memset(usb_midi_data, 0, sizeof(usb_midi_data));

    // 遍历输入数据，每 3 字节一组
    for (i = 0; i < len; i += 3)
    {
        // 检查剩余字节是否不足 3 字节，避免越界
        if (i + 3 > len) {
            break;
        }

        // 根据 MIDI 状态字计算 CIN 值
        uint8_t status = data[i];
        if ((status & 0xF0) == 0x80) { // Note Off
            cin = 0x8;
        } else if ((status & 0xF0) == 0x90) { // Note On
            cin = 0x9;
        } else if ((status & 0xF0) == 0xA0) { // Polyphonic Key Pressure
            cin = 0xA;
        } else if ((status & 0xF0) == 0xB0) { // Control Change
            cin = 0xB;
        } else if ((status & 0xF0) == 0xC0) { // Program Change
            cin = 0xC;
        } else if ((status & 0xF0) == 0xD0) { // Channel Pressure
            cin = 0xD;
        } else if ((status & 0xF0) == 0xE0) { // Pitch Bend Change
            cin = 0xE;
        } else if (status == 0xF0 || status == 0xF7) { // System Exclusive Start/End
            cin = 0x4;
        } else if (status == 0xF2) { // Song Position Pointer
            cin = 0x2;
        } else if (status == 0xF3) { // Song Select
            cin = 0x3;
        } else {
            cin = 0; // 未知状态，跳过
            continue;
        }

        // 添加 CIN 和 3 字节 MIDI 数据到 USB MIDI 数据缓冲区
        usb_midi_data[usb_data_length++] = cin;
        usb_midi_data[usb_data_length++] = data[i];
        usb_midi_data[usb_data_length++] = data[i + 1];
        usb_midi_data[usb_data_length++] = data[i + 2];

        // 检查 USB 数据缓冲区是否满，避免越界
        if (usb_data_length >= sizeof(usb_midi_data)) {
            break;
        }
    }

    // 调用 USBD_CUSTOM_HID_SendReport 发送处理后的 USB MIDI 数据
    return USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, usb_midi_data, usb_data_length);
}





